package nl.unimaas.micc.umsnooker.control.ai.evaluator;

import java.util.HashSet;

import nl.unimaas.micc.umsnooker.control.ai.EventEvaluator;
import nl.unimaas.micc.umsnooker.domain.BilliardBall;
import nl.unimaas.micc.umsnooker.gameflow.GameState;
import nl.unimaas.micc.umsnooker.logic.GameLogicHandler;
import nl.unimaas.micc.umsnooker.simulation.EventHandler;
import nl.unimaas.micc.umsnooker.simulation.InTimeSimulation;
import nl.unimaas.micc.umsnooker.simulation.Simulation;
import nl.unimaas.micc.umsnooker.simulation.event.Event;

public class SimpleScoreEvaluator implements EventEvaluator
{	
	class AIHandler implements EventHandler
	{
		private Simulation sim;
		private GameLogicHandler logicHandler;
		private int eventCount;
		
		public AIHandler(Simulation sim, GameLogicHandler logicHandler)
		{
			this.sim = sim;
			this.logicHandler = logicHandler;
			eventCount = 0;
		}

		@Override
		public void handle(Event e)
		{
			eventCount++;
			if (eventCount>10000 && logicHandler.getPottedScore()==0 || logicHandler.foulOccured())
			{
				sim.pause();
			}
		}
	};

	@Override
	public double evaluate(Event event, GameState state)
	{
		HashSet<Event> eventSet = new HashSet<Event>();
		eventSet.add(event);

		double maxScore = 0;
		for (BilliardBall.Type type : state.getOnBalls())
		{
			maxScore = Math.max(maxScore, type.getValue());
		}
		InTimeSimulation sim = new InTimeSimulation(state.getBalls(), state.getTable());
		sim.init(eventSet);
		GameLogicHandler logicHandler;
		
		logicHandler = new GameLogicHandler(state);
		sim.addEventHandler(logicHandler);
		sim.addEventHandler(new AIHandler(sim, logicHandler));
		
		sim.finish();
		
		if (sim.isPaused())
		{
			// simulation has been aborted
			return -1;
		}
		
		logicHandler.evaluateEvents();
				
		if (logicHandler.foulOccured())
		{
			return -((double) logicHandler.getFoulScore())/7f; //TODO magic number
		}
		else
		{
			return ((double) logicHandler.getPottedScore())/maxScore;
		}
	}

}
